123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- "use client";
- import { Wallet } from "@/api/user";
- import { ChannelType, getWithDrawApi, WithDrawType } from "@/api/withdraw";
- import { clearWallet } from "@/app/[locale]/(navbar)/withdraw/actions";
- import Box from "@/components/Box";
- import ButtonOwn from "@/components/ButtonOwn";
- import Empty from "@/components/Empty";
- import TipsModal, { ModalProps } from "@/components/TipsModal";
- import { useUserInfoStore } from "@/stores/useUserInfoStore";
- import { useWalletStore } from "@/stores/useWalletStore";
- import { isEmail } from "@/utils";
- import { ActionSheet, Form, Input, Toast } from "antd-mobile";
- import type { Action } from "antd-mobile/es/components/action-sheet";
- import { FormInstance } from "antd-mobile/es/components/form";
- import { useTranslations } from "next-intl";
- import Link from "next/link";
- import { FC, Fragment, useRef, useState } from "react";
- import "./page.scss";
- interface Props {
- channels: WithDrawType[];
- wallet: Wallet;
- }
- export enum ChannelEnum {
- CPF = 1,
- Email,
- Phone,
- CNPJ,
- }
- type FieldValueType = {
- account_no: string;
- channel_id: (typeof ChannelEnum)[keyof typeof ChannelEnum];
- type: number;
- };
- interface MobileFieldProps {
- value?: FieldValueType;
- onChange?: (value: FieldValueType) => void;
- actions: Array<ChannelType & { text: string; key: number }>;
- }
- const MobileField: FC<MobileFieldProps> = (props) => {
- const {
- actions,
- value = { account_no: "", channel_id: actions[0].id, type: actions[0].type },
- onChange,
- } = props;
- let [visible, setVisible] = useState(false);
- const t = useTranslations("WithdrawPage");
- let [prefix, setPrefix] = useState<ChannelType & { text: string; key: number }>(actions[0]);
- let [placeholder, setPlaceholder] = useState("000.000.000-00");
- const onAction = (item: any) => {
- setPrefix(item);
- onRealValueChange("");
- if (item.type === ChannelEnum.CPF) {
- setPlaceholder("000.000.000-00");
- return;
- }
- if (item.type === ChannelEnum.Phone) {
- setPlaceholder("11 dígitos");
- return;
- }
- if (item.type === ChannelEnum.Email) {
- setPlaceholder("Email");
- return;
- }
- };
- const onRealValueChange = (value: string) => {
- if (onChange) {
- onChange({ account_no: value, channel_id: prefix.id, type: prefix.type });
- }
- };
- return (
- <>
- <div className="flex">
- <div onClick={() => setVisible(true)} className={"mr-[0.1rem] flex flex-shrink-0"}>
- <span className={"mr-[0.1rem]"}>{prefix.text}</span>
- <span className="iconfont icon-xialaxuanze"></span>
- </div>
- <Input
- name="secretKey"
- value={value.account_no}
- placeholder={placeholder}
- onChange={onRealValueChange}
- />
- </div>
- <ActionSheet
- extra=""
- cancelText={t("Cancelar")}
- visible={visible}
- actions={actions}
- style={{ background: "#fff" }}
- closeOnAction={true}
- getContainer={null}
- onAction={onAction}
- onClose={() => setVisible(false)}
- />
- </>
- );
- };
- const WithdrawWidget: FC<Props> = (props) => {
- const t = useTranslations();
- const { channels, wallet } = props;
- const score = useWalletStore((state) => state.score)!;
- const withdrawRef = useRef<ModalProps>(null);
- const formRef = useRef<FormInstance>(null);
- const [activeWallet, setActiveWallet] = useState<WithDrawType>(channels[0]);
- const walletAction =
- activeWallet &&
- activeWallet.channels?.map((item) => ({
- text: ChannelEnum[item.type],
- key: item.id,
- ...item,
- }));
- const defaultActions: Array<Action & { id: number }> = [
- { text: "CPF", key: "CPF", id: ChannelEnum.CPF },
- { text: t("WithdrawPage.Número"), key: "Celular", id: ChannelEnum.Phone },
- { text: "EMAIL", key: "EMAIL", id: ChannelEnum.Email },
- ];
- const userInfo = useUserInfoStore((state) => state.userInfo);
- const initParams = {
- channel: "",
- amount: "",
- passport: userInfo.passport,
- user_name: userInfo.user_name,
- };
- const AmountValidator = (rules: any, value: string) => {
- const num = +value;
- if (num > activeWallet.max_amount) {
- return Promise.reject(
- new Error(t("WithdrawPage.amountReg", { max: activeWallet.max_amount }))
- );
- }
- if (score && num > score) {
- return Promise.reject(new Error(t("WithdrawPage.amountMaxReg")));
- }
- return Promise.resolve();
- };
- const ChannelValidator = (rules: any, value: FieldValueType) => {
- if (!value.account_no) return Promise.reject(new Error(t("WithdrawPage.channel")));
- if (value.type === ChannelEnum.CPF) {
- return value.account_no.length !== 11
- ? Promise.reject(new Error(t("WithdrawPage.cpfReg")))
- : Promise.resolve();
- }
- if (value.type === ChannelEnum.Email) {
- return isEmail(value.account_no)
- ? Promise.resolve()
- : Promise.reject(new Error(t("WithdrawPage.EmailReg")));
- }
- if (value.type === ChannelEnum.Phone) {
- return value.account_no.length < 11
- ? Promise.reject(new Error(t("WithdrawPage.phoneReg")))
- : Promise.resolve();
- }
- return Promise.resolve();
- };
- const onFinish = async (value: any) => {
- const params = { ...value, ...value.channel, amount: +value.amount };
- getWithDrawApi(params)
- .then((res) => {
- if (res.code === 200) {
- Toast.show(t("code.200"));
- }
- })
- .catch((error) => {
- Toast.show(t(`code.${error.data.code}`));
- });
- await clearWallet();
- };
- if (!activeWallet) return <Empty />;
- return (
- <>
- <Box className={"custom-form"}>
- <div className="withdraw-box">
- <div className="img-box"></div>
- <div className={"mb-[0.1rem] flex flex-wrap gap-[0.0347rem]"}>
- {channels.map((item) => {
- return (
- <Fragment key={item.id}>
- <p
- className={`btn-box ${activeWallet.id === item.id ? "active" : ""}`}
- onClick={() => {
- formRef.current?.resetFields();
- setActiveWallet(item);
- }}
- >
- {item.name}
- </p>
- </Fragment>
- );
- })}
- </div>
- <h1>{t("WithdrawPage.Certifique")}</h1>
- <p className={"text-[0.1rem] text-[#3bc117]"}>{t("WithdrawPage.keyTips")}</p>
- {/* form */}
- <Form
- style={{
- "--border-bottom": "none",
- "--border-top": "none",
- "--border-inner": "none",
- }}
- ref={formRef}
- onFinish={onFinish}
- initialValues={initParams}
- disabled={!activeWallet.channels}
- hasFeedback={!!activeWallet.channels}
- className={"mt-[0.1rem]"}
- footer={<ButtonOwn active>{t("WithdrawPage.Saque")}</ButtonOwn>}
- >
- <Form.Item
- name="user_name"
- label=""
- rules={[{ required: true, message: t("WithdrawPage.usernameReg") }]}
- >
- <Input placeholder={t("WithdrawPage.username")} />
- </Form.Item>
- <Form.Item
- name="passport"
- label=""
- rules={[
- {
- required: true,
- message: t("WithdrawPage.cpfReg"),
- min: 6,
- max: 20,
- },
- ]}
- >
- <Input
- placeholder={t("WithdrawPage.cpf")}
- maxLength={20}
- type={"text"}
- />
- </Form.Item>
- <p className={"my-[0.1rem]"}>{t("WithdrawPage.Tipo")}</p>
- {activeWallet.channels?.length && (
- <Form.Item
- name="channel"
- label=""
- rules={[{ validator: ChannelValidator }]}
- >
- <MobileField actions={walletAction || []} />
- </Form.Item>
- )}
- <h1>{t("WithdrawPage.Vincule")}</h1>
- <p className={"my-[0.1rem]"}>{t("WithdrawPage.Montante")} (BRL):</p>
- <Form.Item
- name="amount"
- label=""
- rules={[
- { required: true, message: t("WithdrawPage.amount") },
- {
- type: "number",
- validator: AmountValidator,
- },
- ]}
- >
- <Input
- placeholder={`Mín. ${activeWallet.min_amount || 0}`}
- type={"number"}
- min={activeWallet.min_amount}
- />
- </Form.Item>
- <ul className="ul-box">
- <li>
- {t("WithdrawPage.SaqueDisponivel")}{" "}
- <span className="tip">{wallet.score} BRL</span>
- </li>
- <li>
- {t("WithdrawPage.Valor")} <span className="tip">0 BRL</span>{" "}
- <span
- className="iconfont icon-iconhelp"
- onClick={() => withdrawRef.current?.onOpen()}
- ></span>
- </li>
- <li>
- {t("WithdrawPage.Para")},{" "}
- <Link href="/" className="toHome router-link-active" replace>
- {t("WithdrawPage.Aposte")}
- </Link>
- </li>
- </ul>
- </Form>
- </div>
- </Box>
- <TipsModal title={"提现弹窗"} ref={withdrawRef}>
- <ul>
- <li>1</li>
- <li>2</li>
- <li>3</li>
- <li>4</li>
- </ul>
- </TipsModal>
- </>
- );
- };
- export default WithdrawWidget;
|